package top.malaoshi.webmvc.parameter;

import top.malaoshi.webmvc.info.MethodsArgumentInfo;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 根据bean中的属性名，从request取值，并赋值
 */
public class BeanResolver extends AbstractResolver implements RequestParamAndMethodArgsResolver {
    @Override
    public Object resolver(HttpServletRequest request,
                           HttpServletResponse response ,
                           MethodsArgumentInfo mai) {

        checkNameAndValue(mai);
        // 从注解获取name、value，或者获取形参名，作为前缀
        String name = getName(mai);

        Class type = mai.getType();
        Object ret = null;
        try {
            ret = type.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(type);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for(PropertyDescriptor pro : propertyDescriptors) {
                // 忽略class
                if("class".equals(pro.getName())){
                    continue;
                }
                Class<?> propertyType = pro.getPropertyType();
                if(propertyType != String.class){
                    continue;
                }
                String propertyName = pro.getName();
                Method writeMethod = pro.getWriteMethod();
                // 如果该属性有setter方法，那么就从request对象中取值
                if(writeMethod!=null){
                    String parameter = request.getParameter(name+"."+propertyName);
                    writeMethod.invoke(ret,parameter);
                }

            }
//            checkRequired(ret,mai);
            return ret;
        } catch (IntrospectionException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}
